//编程实务中， 如果读取对象内部的某个属性， 往往需要判断一下该对象是否存在。 比如， 要读取message.body.user.firstName， 安全的写法是写成下面这样。
// 错误的写法
const firstName = message.body.user.firstName;

// 正确的写法
const firstName = (message &&
	message.body &&
	message.body.user &&
	message.body.user.firstName) || 'default';
//上面例子中， firstName属性在对象的第四层， 所以需要判断四次， 每一层是否有值。


/*
这样的层层判断非常麻烦，因此 ES2020 引入了“链判断运算符”（optional chaining operator） =>  ?. <=  简化上面的写法。
*/

const firstName = message ? .body ? .user ? .firstName || 'default'; //有一个为null或者undefined就断掉不走了
const fooValue = myForm.querySelector('input[name=foo]') ? .value

//下面是判断对象方法是否存在，如果存在就立即执行的例子。
iterator.return ? .()
//上面代码中，iterator.return如果有定义，就会调用该方法，否则iterator.return直接返回undefined，不再执行?.后面的部分。


//对于那些可能没有实现的方法，这个运算符尤其有用。
if (myForm.checkValidity ? .() === false) {
	// 表单校验失败
	return;
}
//老式浏览器的表单可能没有checkValidity这个方法，这时?.运算符就会返回undefined，判断语句就变成了undefined === false，所以就会跳过下面的代码。


/*
链判断运算符有三种用法。

   1-- obj?.prop // 对象属性
   2--obj?.[expr] // 同上
   3--func?.(...args) // 函数或对象方法的调用
   
*/

//下面是obj ? . [expr] 用法的一个例子。
let hex = "#C0FFEE".match(/#([A-Z]+)/i) ? . [1]; //如果匹配成功就返回结果集第二位



//以下为 链式运算符 完爆 三目运算符 的案例 注意 => ?. 为假时直接返回 undefined 整个运算等于没写失效了
a ? .b
// 等同于
a == null ? undefined : a.b

a ? . [x]
// 等同于
a == null ? undefined : a[x]

a ? .b()
// 等同于
a == null ? undefined : a.b()

a ? .()
// 等同于
a == null ? undefined : a()

书签 短路机制
打住先不要看了, 目前链式运算符尚未普及开来, 无法使用
